package zjh_20230328;

import zjh_20230327.Recover;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import static java.lang.System.in;

public class DBUtils<T> {

    private String url;
    private String username;
    private String password;

    private Connection conn;
    private PreparedStatement ps;

    private ResultSet resultSet;
    private static Properties prop;

    static {
        InputStream in = DBUtils.class.getResourceAsStream("db.properties");
        Properties properties = new Properties();
        try {
            properties.load(in);
            DBUtils.prop = properties;
            Class.forName(properties.getProperty("jdbc.driver"));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    public DBUtils() {
        if (prop != null) {
            this.url = prop.getProperty("jdbc.url");
            this.username = prop.getProperty("jdbc.user");
            this.password = prop.getProperty("jdbc.password");
        } else {
            throw new NullPointerException("没配置数据库参数");
        }
    }

    public DBUtils(String url, String user, String password) {
        this.url = url;
        this.username = user;
        this.password = password;
    }

    /**
     * 获取连接
     *
     * @return
     */
    private Connection getConnection() {
        if (url != null && username != null && password != null) {
            try {
                return DriverManager.getConnection(url, username, password);
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        throw new NullPointerException("数据库连接参数为null");
    }


    /**
     * 增删改
     *
     * @return
     */
    public int excuteUpdate(String sql, Object... arr) throws SQLException {
        conn = getConnection();
        ps = conn.prepareStatement(sql);
        for (int i = 0; i < arr.length; i++) {
            ps.setObject(i + 1, arr[i]);
        }
        int i = ps.executeUpdate();
        return i;
    }

    ;

    public T SelectOne(String sql, Class<T> cla, Object... arr) {
        try {
            ResultSet resultSet1 = excuteQuery(sql, arr);
            if (resultSet1.next()) {
                return maper(resultSet1, cla);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    private T maper(ResultSet resultSet, Class cla) {
        try {
            Constructor<T> constructor = cla.getConstructor();
            T t = constructor.newInstance();


            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            for (int i = 0; i < columnCount; i++) {
                String columnLabel = metaData.getColumnLabel(i + 1);
                Object value = resultSet.getObject(columnLabel);
                if (value == null) {
                    continue;
                }

                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnLabel, cla);
                Method writeMethod = propertyDescriptor.getWriteMethod();
                writeMethod.setAccessible(true);
                writeMethod.invoke(t, value);

            }
            return t;

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }


    }

    public List<T> Select(String sql, Class<T> cla, Object... arr) throws SQLException {
        resultSet = excuteQuery(sql, arr);
        List<T> list = new ArrayList<>();
        while (resultSet.next()) {
            list.add(maper(resultSet, cla));
        }
        return list;
    }

    /**
     * 查询
     *
     * @return
     */
    public ResultSet excuteQuery(String sql, Object... arr) throws SQLException {
        conn = getConnection();
        ps = conn.prepareStatement(sql);
        for (int i = 0; i < arr.length; i++) {
            ps.setObject(i + 1, arr[i]);
        }
        resultSet = ps.executeQuery();
        return resultSet;
    }

    ;

    public void close() throws SQLException {
        if (ps != null) {
            ps.close();
        }
        if (conn != null) {
            conn.close();
        }
    }
}
